home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / program / 317 / asmsrc / read.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-10-20  |  51.7 KB  |  1,906 lines

  1. /* read.c - read a source file - Copyright(C)1986 Free Software Foundation */
  2.  
  3. /* Copyright (C) 1986,1987 Free Software Foundation, Inc.
  4.  
  5. This file is part of Gas, the GNU Assembler.
  6.  
  7. The GNU assembler is distributed in the hope that it will be
  8. useful, but WITHOUT ANY WARRANTY.  No author or distributor
  9. accepts responsibility to anyone for the consequences of using it
  10. or for whether it serves any particular purpose or works at all,
  11. unless he says so in writing.  Refer to the GNU Assembler General
  12. Public License for full details.
  13.  
  14. Everyone is granted permission to copy, modify and redistribute
  15. the GNU Assembler, but only under the conditions described in the
  16. GNU Assembler General Public License.  A copy of this license is
  17. supposed to have been given to you along with the GNU Assembler
  18. so you can know your rights and responsibilities.  It should be
  19. in a file named COPYING.  Among other things, the copyright
  20. notice and this notice must be preserved on all copies.  */
  21.  
  22. #define MASK_CHAR (0xFF)    /* If your chars aren't 8 bits, you will
  23.                    change this a bit.  But then, GNU isn't
  24.                    spozed to run on your machine anyway.
  25.                    (RMS is so shortsighted sometimes.)
  26.                  */
  27.  
  28. #define MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT (16)
  29.                 /* This is the largest known floating point */
  30.                 /* format (for now). It will grow when we */
  31.                 /* do 4361 style flonums. */
  32.  
  33.  
  34. /* Routines that read assembler source text to build spagetti in memory. */
  35. /* Another group of these functions is in the as-expr.c module */
  36.  
  37. #include <ctype.h>
  38.  
  39. #ifdef atarist
  40. #include <types.h>
  41. #include <stat.h>
  42. #else
  43. #include <sys/types.h>
  44. #include <sys/stat.h>
  45. #endif
  46.  
  47. #include "as.h"
  48. #include "read.h"
  49. #include "md.h"
  50. #include "hash.h"
  51. #include "obstack.h"
  52. #include "frags.h"
  53. #include "flonum.h"
  54. #include "struc-symbol.h"
  55. #include "expr.h"
  56. #include "symbols.h"
  57.  
  58. char *    input_line_pointer;    /* -> next char of source file to parse. */
  59.  
  60.  
  61. #if BITS_PER_CHAR != 8
  62. The following table is indexed by [ (char) ] and will break if
  63. a char does not have exactly 256 states (hopefully 0:255!) !
  64. #endif
  65.  
  66. char                /* used by is_... macros. our ctype[] */
  67. lex_type [256] = {
  68.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,       /* @ABCDEFGHIJKLMNO */
  69.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,       /* PQRSTUVWXYZ[\]^_ */
  70.   0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,       /* _!"#$%&'()*+,-./ */
  71.   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,       /* 0123456789:;<=>? */
  72.   0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,       /* @ABCDEFGHIJKLMNO */
  73.   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3,       /* PQRSTUVWXYZ[\]^_ */
  74.   0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,       /* `abcdefghijklmno */
  75.   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0,       /* pqrstuvwxyz{|}~. */
  76.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  77.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  78.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  79.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  80.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  81.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  82.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 
  83. };
  84.  
  85.  
  86. /*
  87.  * In: a character.
  88.  * Out: TRUE if this character ends a line.
  89.  */
  90. #define _ (0)
  91. char is_end_of_line [256] = {
  92.  _, _, _, _, _, _, _, _, _, _,99, _, _, _, _, _, /* @abcdefghijklmno */
  93.  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
  94.  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
  95.  _, _, _, _, _, _, _, _, _, _, _,99, _, _, _, _, /* 0123456789:;<=>? */
  96.  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
  97.  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
  98.  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
  99.  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
  100.  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
  101.  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
  102.  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
  103.  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /*                  */
  104.  _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _  /*                  */
  105. };
  106. #undef _
  107.  
  108.                 /* Functions private to this file. */
  109. void        big_cons();
  110. void        cons();
  111. char*        demand_copy_C_string();
  112. char*        demand_copy_string();
  113. void        demand_empty_rest_of_line();
  114. void        float_cons();
  115. long int    get_absolute_expression();
  116. char        get_absolute_expression_and_terminator();
  117. segT        get_known_segmented_expression();
  118. void        ignore_rest_of_line();
  119. int        is_it_end_of_statement();
  120. void        pobegin();
  121. void        pseudo_set();
  122. void        stab();
  123. void        stringer();
  124.  
  125. extern char line_comment_chars[];
  126.  
  127. static char *    buffer_limit;    /* -> 1 + last char in buffer. */
  128.  
  129. static char *    bignum_low;    /* Lowest char of bignum. */
  130. static char *    bignum_limit;    /* 1st illegal address of bignum. */
  131. static char *    bignum_high;    /* Highest char of bignum. */
  132.                 /* May point to (bignum_start-1). */
  133.                 /* Never >= bignum_limit. */
  134. static char *old_buffer = 0;    /* JF a hack */
  135. static char *old_input;
  136. static char *old_limit;
  137.  
  138. void
  139. read_begin()
  140. {
  141.   pobegin();
  142.   obstack_begin( ¬es, 5000 );
  143. #define BIGNUM_BEGIN_SIZE (16)
  144.   bignum_low = xmalloc((long)BIGNUM_BEGIN_SIZE);
  145.   bignum_limit = bignum_low + BIGNUM_BEGIN_SIZE;
  146. }
  147.  
  148. /* set up pseudo-op tables */
  149.  
  150. static struct hash_control *
  151. po_hash = NULL;            /* use before set up: NULL-> address error */
  152.  
  153.  
  154. void    s_abort(),    s_align(),    s_comm(),    s_data();
  155. void    s_desc(),    s_even(),    s_file(),    s_fill();
  156. void    s_gdbbeg(),    s_gdbblock(),    s_gdbend(),    s_gdbsym();
  157. void    s_globl(),    s_lcomm(),    s_line(),    s_lsym();
  158. void    s_org(),    s_set(),    s_space(),    s_text();
  159. void    s_gdbline(),    s_gdblinetab();
  160.  
  161. void    stringer();
  162. void    cons();
  163. void    float_cons();
  164. void    big_cons();
  165. void    stab();
  166.  
  167. static pseudo_typeS
  168. potable[] =
  169. {
  170.   { "abort",    s_abort,    0    },
  171.   { "align",    s_align,    0    },
  172.   { "ascii",    stringer,    0    },
  173.   { "asciz",    stringer,    1    },
  174.   { "byte",    cons,        1    },
  175.   { "comm",    s_comm,        0    },
  176.   { "data",    s_data,        0    },
  177.   { "desc",    s_desc,        0    },
  178.   { "double",    float_cons,    'D'    },
  179.   { "file",    s_file,        0    },
  180.   { "fill",    s_fill,        0    },
  181.   { "float",    float_cons,    'F'    },
  182.   { "gdbbeg",    s_gdbbeg,    0    },
  183.   { "gdbblock",    s_gdbblock,    0    },
  184.   { "gdbend",    s_gdbend,    0    },
  185.   { "gdbsym",    s_gdbsym,    0    },
  186.   { "gdbline",    s_gdbline,    0    },
  187.   { "gdblinetab",s_gdblinetab,    0,    },
  188.   { "globl",    s_globl,    0    },
  189.   { "int",    cons,        4    },
  190.   { "lcomm",    s_lcomm,    0    },
  191.   { "line",    s_line,        0    },
  192.   { "long",    cons,        4    },
  193.   { "lsym",    s_lsym,        0    },
  194.   { "octa",    big_cons,        16    },
  195.   { "org",    s_org,        0    },
  196.   { "quad",    big_cons,    8    },
  197.   { "set",    s_set,        0    },
  198.   { "short",    cons,        2    },
  199.   { "space",    s_space,    0    },
  200.   { "stabd",    stab,        'd'    },
  201.   { "stabn",    stab,        'n'    },
  202.   { "stabs",    stab,        's'    },
  203.   { "text",    s_text,        0    },
  204.   { "word",    cons,        2    },
  205.   { NULL}    /* end sentinel */
  206. };
  207.  
  208. static void
  209. pobegin()
  210. {
  211.   char *    errtxt;        /* error text */
  212.   pseudo_typeS * pop;
  213.  
  214.   po_hash = hash_new();
  215.   errtxt = "";            /* OK so far */
  216.   for (pop=potable; pop->poc_name && !*errtxt; pop++)
  217.     {
  218.       errtxt = hash_insert (po_hash, pop->poc_name, (char *)pop);
  219.     }
  220.  
  221.   for(pop=md_pseudo_table; pop->poc_name && !*errtxt; pop++)
  222.       errtxt = hash_insert (po_hash, pop->poc_name, (char *)pop);
  223.  
  224.   if (*errtxt)
  225.     {
  226.       as_fatal ("error constructing pseudo-op table");
  227.     }
  228. }                /* pobegin() */
  229.  
  230. /*            read_a_source_file()
  231.  *
  232.  * File has already been opened, and will be closed by our caller.
  233.  *
  234.  * We read the file, putting things into a web that
  235.  * represents what we have been reading.
  236.  */
  237. void
  238. read_a_source_file (buffer)
  239.      char *    buffer;        /* 1st character of each buffer of lines is here. */
  240. {
  241.   register char        c;
  242.   register char *    s;    /* string of symbol, '\0' appended */
  243.   register unsigned    u;    /* what kind of pseudo-operation */
  244.   register int        temp;
  245.   /* register struct frag * fragP; JF unused */    /* a frag we just made */
  246.        long int    temp_size;
  247.        long int    temp_repeat;
  248.   register long int    temp_fill;
  249.        char *    p;
  250.   register symbolS *    symbolP;
  251.        int        length;
  252.   register segT        segment;
  253.            expressionS    exp;    /* Build expression values here. */
  254.   register char *    name;    /* Point to a symbol name in the input_line_buffer. */
  255.   pseudo_typeS    *pop;
  256.   void gdb_block_beg();
  257.   void gdb_block_position();
  258.   void gdb_block_end();
  259.   void gdb_symbols_fixup();
  260.  
  261.   subseg_new (SEG_TEXT, 0);
  262.   while ( buffer_limit = input_scrub_next_buffer (&buffer) )
  263.     {                /* We have another line to parse. */
  264.       know( buffer_limit [-1] == '\n' ); /* Must have a sentinel. */
  265.       input_line_pointer = buffer;
  266.  contin:    /* JF this goto is my fault I admit it.  Someone brave please re-write
  267.            the whole input section here?  Pleeze??? */
  268.       while ( input_line_pointer < buffer_limit )
  269.     {            /* We have more of this buffer to parse. */
  270.       /*
  271.        * We now have input_line_pointer -> 1st char of next line.
  272.        * If input_line_pointer [-1] == '\n' then we just
  273.        * scanned another line: so bump line counters.
  274.        */
  275.       if (input_line_pointer [-1] == '\n')
  276.         {
  277.           bump_line_counters ();
  278.         }
  279.       /*
  280.        * We are at the begining of a line, or similar place.
  281.        * We expect a well-formed assembler statement.
  282.        * A "symbol-name:" is a statement.
  283.        *
  284.        * Depending on what compiler is used, the order of these tests
  285.        * may vary to catch most common case 1st.
  286.        * Each test is independent of all other tests at the (top) level.
  287.        * PLEASE make a compiler that doesn't use this assembler.
  288.        * It is crufty to waste a compiler's time encoding things for this
  289.        * assembler, which then wastes more time decoding it.
  290.        * (And communicating via (linear) files is silly!
  291.        * If you must pass stuff, please pass a tree!)
  292.        */
  293.       if ( (c= * input_line_pointer ++) == '\t' || c == ' ')
  294.         {
  295.           c = * input_line_pointer ++;
  296.         }
  297.       know( c != ' ' );    /* No further leading whitespace. */
  298.       /*
  299.        * C is the 1st significant character.
  300.        * Input_line_pointer points after that character.
  301.        */
  302.       if ( is_name_beginner(c) )
  303.         {            /* want user-defined label or pseudo/opcode */
  304.           s = -- input_line_pointer;
  305.           c = get_symbol_end(); /* name's delimiter */
  306.           /*
  307.            * C is character after symbol.
  308.            * That character's place in the input line is now '\0'.
  309.            * S points to the beginning of the symbol.
  310.            *   [In case of pseudo-op, s -> '.'.]
  311.            * Input_line_pointer -> '\0' where c was.
  312.            */
  313.           if ( c == ':' )
  314.         {
  315.           colon(s);    /* user-defined label */
  316.           * input_line_pointer ++ = ':'; /* Put ':' back for error messages' sake. */
  317.                 /* Input_line_pointer -> after ':'. */
  318.           SKIP_WHITESPACE();
  319.         }
  320.           else if(c=='=' || input_line_pointer[1]=='=')        /* JF deal with FOO=BAR */
  321.             {
  322.           equals(s);
  323.           demand_empty_rest_of_line();
  324.         }
  325.           else
  326.         {        /* expect pseudo-op or machine instruction */
  327.           if ( *s=='.' )
  328.             {
  329.               /*
  330.                * PSEUDO - OP.
  331.                *
  332.                * WARNING: c has next char, which may be end-of-line.
  333.                * We lookup the pseudo-op table with s+1 because we
  334.                * already know that the pseudo-op begins with a '.'.
  335.                */
  336.  
  337.               pop= (pseudo_typeS *) hash_find (po_hash, s+1);
  338.                 /* Put it back for error messages etc. */
  339.               * input_line_pointer = c;
  340.                 /* The following skip of whitespace is compulsory. */
  341.                 /* A well shaped space is sometimes all that seperates keyword from operands. */
  342.               if ( c == ' ' || c == '\t' )
  343.             {    /* Skip seperator after keyword. */
  344.               input_line_pointer ++;
  345.             }
  346.               /*
  347.                * Input_line is restored.
  348.                * Input_line_pointer -> 1st non-blank char
  349.                * after pseudo-operation.
  350.                */
  351.                 if(!pop) {
  352.               as_warn("Unknown pseudo-op");
  353.               ignore_rest_of_line();
  354.               break;
  355.             }
  356.             else
  357.               (*pop->poc_handler)(pop->poc_val);
  358.             }
  359.           else
  360.             {        /* machine instruction */
  361.               /* WARNING: c has char, which may be end-of-line. */
  362.               /* Also: input_line_pointer -> `\0` where c was. */
  363.               * input_line_pointer = c;
  364.               while ( ! is_end_of_line [* input_line_pointer] )
  365.             {
  366.               input_line_pointer ++;
  367.             }
  368.               c = * input_line_pointer;
  369.               * input_line_pointer = '\0';
  370.               md_assemble (s);    /* Assemble 1 instruction. */
  371.               * input_line_pointer ++ = c;
  372.               /* We resume loop AFTER the end-of-line from this instruction */
  373.             }        /* if (*s=='.') */
  374.         }        /* if c==':' */
  375.           continue;
  376.         }            /* if (is_name_beginner(c) */
  377.  
  378.  
  379.       if ( is_end_of_line [c] )
  380.         {            /* empty statement */
  381.           continue;
  382.         }
  383.  
  384.       if ( isdigit(c) )
  385.         {            /* local label  ("4:") */
  386.           temp = c - '0';
  387.           if ( * input_line_pointer ++ == ':' )
  388.         {
  389.           local_colon (temp);
  390.         }
  391.           else
  392.         {
  393.           as_warn( "Spurious digit %d.", temp);
  394.           input_line_pointer -- ;
  395.           ignore_rest_of_line();
  396.         }
  397.           continue;
  398.         }
  399.       if(c && index(line_comment_chars,c)) {    /* Its a comment.  Better say APP or NO_APP */
  400.         char *ends,*to_buf;
  401.         int to_length;
  402.         struct stat stbuf;
  403.         char *strstr();
  404.         char    *new_buf;
  405.         int    new_length;
  406.  
  407.         s=input_line_pointer;
  408.         if(strncmp(s,"APP\n",4))
  409.             continue;    /* We ignore it */
  410.         s+=4;
  411.  
  412.         ends=strstr(s,"#NO_APP\n");
  413.  
  414.         if(!ends) {
  415.             char    *tmp_buf;
  416.             int    tmp_len;
  417.             int    num;
  418.  
  419.             /* The end of the #APP wasn't in this buffer.  We
  420.                keep reading in buffers until we find the #NO_APP
  421.                that goes with this #APP  There is one.  The specs
  422.                 guarentee it. . .*/
  423.             tmp_len=buffer_limit-s;
  424.             tmp_buf=xmalloc(tmp_len);
  425.             bcopy(s,tmp_buf,tmp_len);
  426.             do {
  427.                 char *new_end;
  428.  
  429.                 new_end = input_scrub_next_buffer(&buffer);
  430.                 if(!new_end)
  431.                     break;
  432.                 else
  433.                     buffer_limit = new_end;
  434.                 input_line_pointer = buffer;
  435.                 ends = strstr(buffer,"#NO_APP\n");
  436.                 if(ends)
  437.                     num=ends-buffer;
  438.                 else
  439.                     num=buffer_limit-buffer;
  440.  
  441.                 tmp_buf=xrealloc(tmp_buf,tmp_len+num);
  442.                 bcopy(buffer,tmp_buf+tmp_len,num);
  443.                 tmp_len+=num;
  444.             } while(!ends);
  445.             do_scrub(0,0,tmp_buf,tmp_len,&new_buf,&new_length);
  446.             free(tmp_buf);
  447.             input_line_pointer= ends ? ends+8 : NULL;
  448.         } else {
  449.             do_scrub(0,0,s,ends-s,&new_buf,&new_length);
  450.             input_line_pointer=ends+8;
  451.         }
  452.         old_buffer=buffer;
  453.         old_input=input_line_pointer;
  454.         old_limit=buffer_limit;
  455.         buffer=new_buf;
  456.         input_line_pointer=new_buf;
  457.         buffer_limit=new_buf+new_length;
  458.         continue;
  459.       }
  460.  
  461.       as_warn("Junk character %d.",c);
  462.       ignore_rest_of_line();
  463.     }            /* while (input_line_pointer<buffer_limit )*/
  464.     if(old_buffer) {
  465.         if(old_input == 0)
  466.             return;
  467.         buffer=old_buffer;
  468.         input_line_pointer=old_input;
  469.         buffer_limit=old_limit;
  470.         old_buffer = 0;
  471.         goto contin;
  472.     }
  473.     }                /* while (more bufrers to scan) */
  474. }                /* read_a_source_file() */
  475.  
  476. void
  477. s_abort()
  478. {
  479.     as_fatal(".abort detected.  Abandoning ship.");
  480. }
  481.  
  482. void
  483. s_align()
  484. {
  485.     register int temp;
  486.     register long int temp_fill;
  487.  
  488.     temp = get_absolute_expression ();
  489. #define MAX_ALIGNMENT (15)
  490.     if ( temp > MAX_ALIGNMENT )
  491.         as_warn("Alignment too large: %d. assumed.", temp = MAX_ALIGNMENT);
  492.     else if ( temp < 0 ) {
  493.         as_warn("Alignment negative. 0 assumed.");
  494.         temp = 0;
  495.     }
  496.     if ( *input_line_pointer == ',' ) {
  497.         input_line_pointer ++;
  498.         temp_fill = get_absolute_expression ();
  499.     } else
  500.         temp_fill = 0;
  501.     /* Only make a frag if we HAVE to. . . */
  502.     if ( temp && ! need_pass_2 )
  503.         frag_align (temp, (int)temp_fill);
  504.     demand_empty_rest_of_line();
  505. }
  506.  
  507. void
  508. s_comm()
  509. {
  510.     register char *name;
  511.     register char c;
  512.     register char *p;
  513.     register int temp;
  514.     register symbolS *    symbolP;
  515.  
  516.     name = input_line_pointer;
  517.     c = get_symbol_end();
  518.     /* just after name is now '\0' */
  519.     p = input_line_pointer;
  520.     *p = c;
  521.     SKIP_WHITESPACE();
  522.     if ( * input_line_pointer != ',' ) {
  523.         as_warn("Expected comma after symbol-name");
  524.         ignore_rest_of_line();
  525.         return;
  526.     }
  527.     input_line_pointer ++; /* skip ',' */
  528.     if ( (temp = get_absolute_expression ()) < 0 ) {
  529.         as_warn(".COMMon length (%d.) <0! Ignored.", temp);
  530.         ignore_rest_of_line();
  531.         return;
  532.     }
  533.     *p = 0;
  534.     symbolP = symbol_find_or_make (name);
  535.     *p = c;
  536.     if (   (symbolP -> sy_type & N_TYPE) != N_UNDF ||
  537.  symbolP -> sy_other != 0 || symbolP -> sy_desc != 0) {
  538.         as_warn( "Ignoring attempt to re-define symbol");
  539.         ignore_rest_of_line();
  540.         return;
  541.     }
  542.     if (symbolP -> sy_value) {
  543.         if (symbolP -> sy_value != temp)
  544.             as_warn( "Length of .comm \"%s\" is already %d. Not changed to %d.",
  545.  symbolP -> sy_name, symbolP -> sy_value, temp);
  546.     } else {
  547.         symbolP -> sy_value = temp;
  548.         symbolP -> sy_type |= N_EXT;
  549.     }
  550.     know( symbolP -> sy_frag == &zero_address_frag );
  551.     demand_empty_rest_of_line();
  552. }
  553.  
  554. void
  555. s_data()
  556. {
  557.     register int temp;
  558.  
  559.     temp = get_absolute_expression ();
  560.     subseg_new (SEG_DATA, (subsegT)temp);
  561.     demand_empty_rest_of_line();
  562. }
  563.  
  564. void
  565. s_desc()
  566. {
  567.     register char *name;
  568.     register char c;
  569.     register char *p;
  570.     register symbolS *    symbolP;
  571.     register int temp;
  572.  
  573.     /*
  574.      * Frob invented at RMS' request. Set the n_desc of a symbol.
  575.      */
  576.     name = input_line_pointer;
  577.     c = get_symbol_end();
  578.     p = input_line_pointer;
  579.     symbolP = symbol_table_lookup (name);
  580.     * p = c;
  581.     SKIP_WHITESPACE();
  582.     if ( * input_line_pointer != ',' ) {
  583.         *p = 0;
  584.         as_warn("Expected comma after name \"%s\"", name);
  585.         *p = c;
  586.         ignore_rest_of_line();
  587.     } else {
  588.         input_line_pointer ++;
  589.         temp = get_absolute_expression ();
  590.         *p = 0;
  591.         symbolP = symbol_find_or_make (name);
  592.         *p = c;
  593.         symbolP -> sy_desc = temp;
  594.     }
  595.     demand_empty_rest_of_line();
  596. }
  597.  
  598. void
  599. s_file()
  600. {
  601.     register char *s;
  602.     int    length;
  603.  
  604.     /* Some assemblers tolerate immediately following '"' */
  605.     if ( s = demand_copy_string( & length ) ) {
  606.         new_logical_line (s, -1);
  607.         demand_empty_rest_of_line();
  608.     }
  609. }
  610.  
  611. void
  612. s_fill()
  613. {
  614.     long int temp_repeat;
  615.     long int temp_size;
  616.     register long int temp_fill;
  617.     char    *p;
  618.  
  619.     if ( get_absolute_expression_and_terminator(& temp_repeat) != ',' ) {
  620.         input_line_pointer --; /* Backup over what was not a ','. */
  621.         as_warn("Expect comma after rep-size in .fill");
  622.         ignore_rest_of_line();
  623.         return;
  624.     }
  625.     if ( get_absolute_expression_and_terminator( & temp_size) != ',' ) {
  626.           input_line_pointer --; /* Backup over what was not a ','. */
  627.           as_warn("Expected comma after size in .fill");
  628.           ignore_rest_of_line();
  629.           return;
  630.     }
  631.     /*
  632.      * This is to be compatible with BSD 4.2 AS, not for any rational reason.
  633.      */
  634. #define BSD_FILL_SIZE_CROCK_8 (8)
  635.     if ( temp_size > BSD_FILL_SIZE_CROCK_8 ) {
  636.         as_warn(".fill size clamped to %d.", BSD_FILL_SIZE_CROCK_8);
  637.         temp_size = BSD_FILL_SIZE_CROCK_8 ;
  638.     } if ( temp_size < 0 ) {
  639.         as_warn("Size negative: .fill ignored.");
  640.         temp_size = 0;
  641.     } else if ( temp_repeat <= 0 ) {
  642.         as_warn("Repeat < 0, .fill ignored");
  643.         temp_size = 0;
  644.     }
  645.     temp_fill = get_absolute_expression ();
  646.     if ( temp_size && !need_pass_2 ) {
  647.         p = frag_var (rs_fill, (int)temp_size, (int)temp_size, (relax_substateT)0, (symbolS *)0, temp_repeat, (char *)0);
  648.         bzero (p, (int)temp_size);
  649. /*
  650.  * The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX flavoured AS.
  651.  * The following bizzare behaviour is to be compatible with above.
  652.  * I guess they tried to take up to 8 bytes from a 4-byte expression
  653.  * and they forgot to sign extend. Un*x Sux.
  654.  */
  655. #define BSD_FILL_SIZE_CROCK_4 (4)
  656.         md_number_to_chars (p, temp_fill, temp_size > BSD_FILL_SIZE_CROCK_4 ? BSD_FILL_SIZE_CROCK_4 : (int)temp_size);
  657. /*
  658.  * Note: .fill (),0 emits no frag (since we are asked to .fill 0 bytes)
  659.  * but emits no error message because it seems a legal thing to do.
  660.  * It is a degenerate case of .fill but could be emitted by a compiler.
  661.  */
  662.     }
  663.     demand_empty_rest_of_line();
  664. }
  665.  
  666. void
  667. s_gdbbeg()
  668. {
  669.     register int temp;
  670.  
  671.     temp = get_absolute_expression ();
  672.     if (temp < 0)
  673.         as_warn( "Block number <0. Ignored." );
  674.     else if (flagseen ['G'])
  675.         gdb_block_beg ( (long int) temp, frag_now, (long int)(obstack_next_free(& frags) - frag_now -> fr_literal));
  676.     demand_empty_rest_of_line ();
  677. }
  678.  
  679. void
  680. s_gdbblock()
  681. {
  682.     register int    position;
  683.     int    temp;
  684.  
  685.     if (get_absolute_expression_and_terminator (&temp) != ',') {
  686.         as_warn( "expected comma before position in .gdbblock");
  687.         --input_line_pointer;
  688.         ignore_rest_of_line ();
  689.         return;
  690.     }
  691.     position = get_absolute_expression ();
  692.     if (flagseen ['G'])
  693.         gdb_block_position ((long int) temp, (long int) position);
  694.     demand_empty_rest_of_line ();
  695. }
  696.  
  697. void
  698. s_gdbend()
  699. {
  700.     register int temp;
  701.  
  702.     temp = get_absolute_expression ();
  703.     if (temp < 0)
  704.         as_warn( "Block number <0. Ignored." );
  705.     else if (flagseen ['G'])
  706.         gdb_block_end ( (long int) temp, frag_now, (long int)(obstack_next_free(& frags) - frag_now -> fr_literal));
  707.     demand_empty_rest_of_line ();
  708. }
  709.  
  710. void
  711. s_gdbsym()
  712. {
  713.     register char *name,
  714.             *p;
  715.     register char c;
  716.     register symbolS *    symbolP;
  717.     register int temp;
  718.  
  719.     name = input_line_pointer;
  720.     c = get_symbol_end();
  721.     p = input_line_pointer;
  722.     symbolP = symbol_find_or_make (name);
  723.     *p = c;
  724.     SKIP_WHITESPACE();
  725.     if ( * input_line_pointer != ',' ) {
  726.         as_warn("Expected comma after name");
  727.         ignore_rest_of_line();
  728.         return;
  729.     }
  730.     input_line_pointer ++;
  731.     if ( (temp = get_absolute_expression ()) < 0 ) {
  732.         as_warn("Bad GDB symbol file offset (%d.) <0! Ignored.", temp);
  733.         ignore_rest_of_line();
  734.         return;
  735.     }
  736.     if (flagseen ['G'])
  737.         gdb_symbols_fixup (symbolP, (long int)temp);
  738.     demand_empty_rest_of_line ();
  739. }
  740.  
  741. void
  742. s_gdbline()
  743. {
  744.     int    file_number,
  745.         lineno;
  746.  
  747.     if(get_absolute_expression_and_terminator(&file_number) != ',') {
  748.         as_warn("expected comman after filenum in .gdbline");
  749.         ignore_rest_of_line();
  750.         return;
  751.     }
  752.     lineno=get_absolute_expression();
  753.     if(flagseen['G'])
  754.         gdb_line(file_number,lineno);
  755.     demand_empty_rest_of_line();
  756. }
  757.  
  758.  
  759. void
  760. s_gdblinetab()
  761. {
  762.     int    file_number,
  763.         offset;
  764.  
  765.     if(get_absolute_expression_and_terminator(&file_number) != ',') {
  766.         as_warn("expected comman after filenum in .gdblinetab");
  767.         ignore_rest_of_line();
  768.         return;
  769.     }
  770.     offset=get_absolute_expression();
  771.     if(flagseen['G'])
  772.         gdb_line_tab(file_number,offset);
  773.     demand_empty_rest_of_line();
  774. }
  775.     
  776.  
  777. void
  778. s_globl()
  779. {
  780.     register char *name;
  781.     register int c;
  782.     register symbolS *    symbolP;
  783.  
  784.     do {
  785.         name = input_line_pointer;
  786.         c = get_symbol_end();
  787.         symbolP = symbol_find_or_make (name);
  788.         * input_line_pointer = c;
  789.         SKIP_WHITESPACE();
  790.         symbolP -> sy_type |= N_EXT;
  791.         if(c==',') {
  792.             input_line_pointer++;
  793.             SKIP_WHITESPACE();
  794.             if(*input_line_pointer=='\n')
  795.                 c='\n';
  796.         }
  797.     } while(c==',');
  798.     demand_empty_rest_of_line();
  799. }
  800.  
  801. void
  802. s_lcomm()
  803. {
  804.     register char *name;
  805.     register char c;
  806.     register char *p;
  807.     register int temp;
  808.     register symbolS *    symbolP;
  809.  
  810.     name = input_line_pointer;
  811.     c = get_symbol_end();
  812.     p = input_line_pointer;
  813.     *p = c;
  814.     SKIP_WHITESPACE();
  815.     if ( * input_line_pointer != ',' ) {
  816.         as_warn("Expected comma after name");
  817.         ignore_rest_of_line();
  818.         return;
  819.     }
  820.     input_line_pointer ++;
  821.     if ( (temp = get_absolute_expression ()) < 0 ) {
  822.         as_warn("BSS length (%d.) <0! Ignored.", temp);
  823.         ignore_rest_of_line();
  824.         return;
  825.     }
  826.     *p = 0;
  827.     symbolP = symbol_find_or_make (name);
  828.     *p = c;
  829.     if (   symbolP -> sy_other == 0
  830.         && symbolP -> sy_desc  == 0
  831.         && (   (   symbolP -> sy_type  == N_BSS
  832.         && symbolP -> sy_value == local_bss_counter)
  833.         || (   (symbolP -> sy_type & N_TYPE) == N_UNDF
  834.         && symbolP -> sy_value == 0))) {
  835.         symbolP -> sy_value = local_bss_counter;
  836.         symbolP -> sy_type  = N_BSS;
  837.         symbolP -> sy_frag  = & bss_address_frag;
  838.         local_bss_counter += temp;
  839.     } else
  840.         as_warn( "Ignoring attempt to re-define symbol from %d. to %d.",
  841.  symbolP -> sy_value, local_bss_counter );
  842.     demand_empty_rest_of_line();
  843. }
  844.  
  845. void
  846. s_line()
  847. {
  848.     /* Assume delimiter is part of expression. */
  849.     /* BSD4.2 as fails with delightful bug, so we */
  850.     /* are not being incompatible here. */
  851.     new_logical_line ((char *)NULL, (int)(get_absolute_expression ()));
  852.     demand_empty_rest_of_line();
  853. }
  854.  
  855. void
  856. s_long()
  857. {
  858.     cons(4);
  859. }
  860.  
  861. void
  862. s_int()
  863. {
  864.     cons(4);
  865. }
  866.  
  867. void
  868. s_lsym()
  869. {
  870.     register char *name;
  871.     register char c;
  872.     register char *p;
  873.     register segT segment;
  874.     expressionS exp;
  875.     register symbolS *symbolP;
  876.  
  877.     /* we permit ANY expression: BSD4.2 demands constants */
  878.     name = input_line_pointer;
  879.     c = get_symbol_end();
  880.     p = input_line_pointer;
  881.     *p = c;
  882.     SKIP_WHITESPACE();
  883.     if ( * input_line_pointer != ',' ) {
  884.         *p = 0;
  885.         as_warn("Expected comma after name \"%s\"", name);
  886.         *p = c;
  887.         ignore_rest_of_line();
  888.         return;
  889.     }
  890.     input_line_pointer ++;
  891.     segment = expression (& exp);
  892.     if (   segment != SEG_ABSOLUTE && segment != SEG_DATA &&
  893.  segment != SEG_TEXT && segment != SEG_BSS) {
  894.         as_warn("Bad expression: %s", seg_name [(int)segment]);
  895.         ignore_rest_of_line();
  896.         return;
  897.     }
  898.  know(   segment == SEG_ABSOLUTE || segment == SEG_DATA || segment == SEG_TEXT || segment == SEG_BSS );
  899.     *p = 0;
  900.     symbolP = symbol_new (name,(unsigned char)(seg_N_TYPE [(int) segment]),
  901.  0, 0, (valueT)(exp . X_add_number), & zero_address_frag);
  902.     *p = c;
  903.     demand_empty_rest_of_line();
  904. }
  905.  
  906. void
  907. s_org()
  908. {
  909.     register segT segment;
  910.     expressionS exp;
  911.     register long int temp_fill;
  912.     register char *p;
  913. /*
  914.  * Don't believe the documentation of BSD 4.2 AS.
  915.  * There is no such thing as a sub-segment-relative origin.
  916.  * Any absolute origin is given a warning, then assumed to be segment-relative.
  917.  * Any segmented origin expression ("foo+42") had better be in the right
  918.  * segment or the .org is ignored.
  919.  *
  920.  * BSD 4.2 AS warns if you try to .org backwards. We cannot because we
  921.  * never know sub-segment sizes when we are reading code.
  922.  * BSD will crash trying to emit -ve numbers of filler bytes in certain
  923.  * .orgs. We don't crash, but see as-write for that code.
  924.  */
  925. /*
  926.  * Don't make frag if need_pass_2==TRUE.
  927.  */
  928.     segment = get_known_segmented_expression(& exp);
  929.     if ( *input_line_pointer == ',' ) {
  930.         input_line_pointer ++;
  931.         temp_fill = get_absolute_expression ();
  932.     } else
  933.         temp_fill = 0;
  934.     if ( ! need_pass_2 ) {
  935.         if (segment != now_seg && segment != SEG_ABSOLUTE)
  936.             as_warn("Illegal segment \"%s\". Segment \"%s\" assumed.",
  937.  seg_name [(int) segment], seg_name [(int) now_seg]);
  938.         p = frag_var (rs_org, 1, 1, (relax_substateT)0, exp . X_add_symbol,
  939.  exp . X_add_number, (char *)0);
  940.         * p = temp_fill;
  941.     } /* if (ok to make frag) */
  942.     demand_empty_rest_of_line();
  943. }
  944.  
  945. void
  946. s_set()
  947. {
  948.     register char *name;
  949.     register char c;
  950.     register char *p;
  951.     register symbolS *symbolP;
  952.  
  953.     /*
  954.      * Especial apologies for the random logic:
  955.      * this just grew, and could be parsed much more simply!
  956.      * Dean in haste.
  957.      */
  958.     name = input_line_pointer;
  959.     c = get_symbol_end();
  960.     p = input_line_pointer;
  961.     *p = c;
  962.     SKIP_WHITESPACE();
  963.     if ( * input_line_pointer != ',' ) {
  964.         *p = 0;
  965.         as_warn("Expected comma after name \"%s\"", name);
  966.         *p = c;
  967.         ignore_rest_of_line();
  968.         return;
  969.     }
  970.     input_line_pointer ++;
  971.     * p = 0;
  972.     symbolP = symbol_find_or_make (name);
  973.     * p = c;
  974.     pseudo_set (symbolP);
  975.     demand_empty_rest_of_line ();
  976. }
  977.  
  978. void
  979. s_space()
  980. {
  981.     long int temp_repeat;
  982.     register long int temp_fill;
  983.     register char *p;
  984.  
  985.     /* Just like .fill, but temp_size = 1 */
  986.     if ( get_absolute_expression_and_terminator( & temp_repeat) == ',' ) {
  987.         temp_fill = get_absolute_expression ();
  988.     } else {
  989.         input_line_pointer --; /* Backup over what was not a ','. */
  990.         temp_fill = 0;
  991.     }
  992.     if ( temp_repeat <= 0 ) {
  993.         as_warn("Repeat < 0, .space ignored");
  994.         ignore_rest_of_line();
  995.         return;
  996.     }
  997.     if ( ! need_pass_2 ) {
  998.         p = frag_var (rs_fill, 1, 1, (relax_substateT)0, (symbolS *)0,
  999.  temp_repeat, (char *)0);
  1000.         * p = temp_fill;
  1001.     }
  1002.     demand_empty_rest_of_line();
  1003. }
  1004.  
  1005. void
  1006. s_text()
  1007. {
  1008.     register int temp;
  1009.  
  1010.     temp = get_absolute_expression ();
  1011.     subseg_new (SEG_TEXT, (subsegT)temp);
  1012.     demand_empty_rest_of_line();
  1013. }
  1014.  
  1015.  
  1016. /*( JF was static, but can't be if machine dependent pseudo-ops are to use it */
  1017.  
  1018. void
  1019. demand_empty_rest_of_line()
  1020. {
  1021.   SKIP_WHITESPACE();
  1022.   if ( is_end_of_line [* input_line_pointer] )
  1023.     {
  1024.       input_line_pointer ++;
  1025.     }
  1026.   else
  1027.     {
  1028.       ignore_rest_of_line();
  1029.     }
  1030.                 /* Return having already swallowed end-of-line. */
  1031. }                /* Return pointing just after end-of-line. */
  1032.  
  1033.  
  1034. void
  1035. ignore_rest_of_line()        /* For suspect lines: gives warning. */
  1036. {
  1037.   if ( ! is_end_of_line [* input_line_pointer])
  1038.     {
  1039.       as_warn("Rest of line ignored. 1st junk character valued %d."
  1040.           , * input_line_pointer);
  1041.       while (   input_line_pointer < buffer_limit
  1042.          && ! is_end_of_line [* input_line_pointer] )
  1043.     {
  1044.       input_line_pointer ++;
  1045.     }
  1046.     }
  1047.   input_line_pointer ++;    /* Return pointing just after end-of-line. */
  1048.   know( is_end_of_line [input_line_pointer [-1]] );
  1049. }
  1050.  
  1051. /*
  1052.  *            stab()
  1053.  *
  1054.  * Handle .stabX directives, which used to be open-coded.
  1055.  * So much creeping featurism overloaded the semantics that we decided
  1056.  * to put all .stabX thinking in one place. Here.
  1057.  *
  1058.  * We try to make any .stabX directive legal. Other people's AS will often
  1059.  * do assembly-time consistency checks: eg assigning meaning to n_type bits
  1060.  * and "protecting" you from setting them to certain values. (They also zero
  1061.  * certain bits before emitting symbols. Tut tut.)
  1062.  *
  1063.  * If an expression is not absolute we either gripe or use the relocation
  1064.  * information. Other people's assemblers silently forget information they
  1065.  * don't need and invent information they need that you didn't supply.
  1066.  *
  1067.  * .stabX directives always make a symbol table entry. It may be junk if
  1068.  * the rest of your .stabX directive is malformed.
  1069.  */
  1070. static void
  1071. stab (what)
  1072. /*      char what;            /* 's'->.stabs, 'n'->.stabn, 'd'->.stabd */
  1073. {
  1074.   register symbolS *    symbolP;
  1075.   register char *    string;
  1076.        int        saved_type;
  1077.          int        length;
  1078.          int        goof;    /* TRUE if we have aborted. */
  1079.        long int    longint;
  1080.  
  1081. /*
  1082.  * Enter with input_line_pointer pointing past .stabX and any following
  1083.  * whitespace.
  1084.  */
  1085.     goof = FALSE; /* JF who forgot this?? */
  1086.     if (what == 's') {
  1087.         string = demand_copy_C_string (& length);
  1088.         SKIP_WHITESPACE();
  1089.         if (* input_line_pointer == ',')
  1090.             input_line_pointer ++;
  1091.         else {
  1092.             as_warn( "I need a comma after symbol's name" );
  1093.             goof = TRUE;
  1094.         }
  1095.     } else
  1096.         string = "";
  1097.  
  1098. /*
  1099.  * Input_line_pointer->after ','.  String -> symbol name.
  1100.  */
  1101.     if (! goof) {
  1102.         symbolP = symbol_new (string, 0,0,0,0,(struct frag *)0);
  1103.         switch (what) {
  1104.         case 'd':
  1105.             symbolP->sy_name = NULL; /* .stabd feature. */
  1106.             symbolP->sy_value = obstack_next_free(& frags) - frag_now->fr_literal;
  1107.             symbolP->sy_frag = frag_now;
  1108.             break;
  1109.  
  1110.         case 'n':
  1111.             symbolP->sy_frag = frag_now;
  1112.             break;
  1113.  
  1114.         case 's':
  1115.             symbolP->sy_frag = & zero_address_frag;
  1116.             break;
  1117.  
  1118.         default:
  1119.             BAD_CASE( what );
  1120.             break;
  1121.         }
  1122.         if (get_absolute_expression_and_terminator (& longint) == ',')
  1123.             symbolP->sy_type = saved_type = longint;
  1124.         else {
  1125.             as_warn( "I want a comma after the n_type expression" );
  1126.             goof = TRUE;
  1127.             input_line_pointer --; /* Backup over a non-',' char. */
  1128.         }
  1129.     }
  1130.     if (! goof) {
  1131.         if (get_absolute_expression_and_terminator (& longint) == ',')
  1132.             symbolP->sy_other = longint;
  1133.         else {
  1134.             as_warn( "I want a comma after the n_other expression" );
  1135.             goof = TRUE;
  1136.             input_line_pointer --; /* Backup over a non-',' char. */
  1137.         }
  1138.     }
  1139.     if (! goof) {
  1140.         symbolP->sy_desc = get_absolute_expression ();
  1141.         if (what == 's' || what == 'n') {
  1142.             if (* input_line_pointer != ',') {
  1143.                 as_warn( "I want a comma after the n_desc expression" );
  1144.                 goof = TRUE;
  1145.             } else {
  1146.                 input_line_pointer ++;
  1147.             }
  1148.         }
  1149.     }
  1150.     if ((! goof) && (what=='s' || what=='n')) {
  1151.         pseudo_set (symbolP);
  1152.         symbolP->sy_type = saved_type;
  1153.     }
  1154.     if (goof)
  1155.         ignore_rest_of_line ();
  1156.     else
  1157.         demand_empty_rest_of_line ();
  1158. }
  1159.  
  1160. /*
  1161.  *            pseudo_set()
  1162.  *
  1163.  * In:    Pointer to a symbol.
  1164.  *    Input_line_pointer -> expression.
  1165.  *
  1166.  * Out:    Input_line_pointer -> just after any whitespace after expression.
  1167.  *    Tried to set symbol to value of expression.
  1168.  *    Will change sy_type, sy_value, sy_frag;
  1169.  *    May set need_pass_2 == TRUE.
  1170.  */
  1171. static void
  1172. pseudo_set (symbolP)
  1173.      symbolS *    symbolP;
  1174. {
  1175.   expressionS    exp;
  1176.   register segT    segment;
  1177.  
  1178.   know( symbolP );        /* NULL pointer is logic error. */
  1179.   if ((segment = expression( & exp )) == SEG_NONE)
  1180.     {
  1181.       as_warn( "Missing expression: absolute 0 assumed" );
  1182.       exp . X_seg        = SEG_ABSOLUTE;
  1183.       exp . X_add_number    = 0;
  1184.     }
  1185.   switch (segment)
  1186.     {
  1187.     case SEG_BIG:
  1188.       as_warn( "%s number illegal. Absolute 0 assumed.",
  1189.           exp . X_add_number > 0 ? "Bignum" : "Floating-Point" );
  1190.       symbolP -> sy_type = N_ABS;
  1191.       symbolP -> sy_value = 0;
  1192.       symbolP -> sy_frag = & zero_address_frag;
  1193.       break;
  1194.  
  1195.     case SEG_NONE:
  1196.       as_warn("No expression:  Using absolute 0");
  1197.       symbolP -> sy_type = N_ABS;
  1198.       symbolP -> sy_value = 0;
  1199.       symbolP -> sy_frag = & zero_address_frag;
  1200.       break;
  1201.  
  1202.     case SEG_DIFFERENCE:
  1203.       as_warn( "Complex expression. Absolute segment assumed." );
  1204.     case SEG_ABSOLUTE:
  1205.       symbolP -> sy_type = N_ABS;
  1206.       symbolP -> sy_value = exp . X_add_number;
  1207.       symbolP -> sy_frag = & zero_address_frag;
  1208.       break;
  1209.  
  1210.     case SEG_DATA:
  1211.     case SEG_TEXT:
  1212.     case SEG_BSS:
  1213.       symbolP -> sy_type = seg_N_TYPE [(int) segment];
  1214.       symbolP -> sy_value= exp . X_add_number + exp . X_add_symbol -> sy_value;
  1215.       symbolP -> sy_frag = exp . X_add_symbol -> sy_frag;
  1216.       break;
  1217.       
  1218.     case SEG_PASS1:        /* Not an error. Just try another pass. */
  1219.       symbolP->sy_forward=exp.X_add_symbol;
  1220.       as_warn("Unknown expression");
  1221.       know( need_pass_2 == TRUE );
  1222.       break;
  1223.       
  1224.     case SEG_UNKNOWN:
  1225.       symbolP->sy_forward=exp.X_add_symbol;
  1226.       /* as_warn("unknown symbol"); */
  1227.       /* need_pass_2 = TRUE; */
  1228.       break;
  1229.       
  1230.     default:
  1231.       BAD_CASE( segment );
  1232.       break;
  1233.     }
  1234. }
  1235.  
  1236. /*
  1237.  *            cons()
  1238.  *
  1239.  * CONStruct more frag of .bytes, or .words etc.
  1240.  * Should need_pass_2 be TRUE then emit no frag(s).
  1241.  * This understands EXPRESSIONS, as opposed to big_cons().
  1242.  *
  1243.  * Bug (?)
  1244.  *
  1245.  * This has a split personality. We use expression() to read the
  1246.  * value. We can detect if the value won't fit in a byte or word.
  1247.  * But we can't detect if expression() discarded significant digits
  1248.  * in the case of a long. Not worth the crocks required to fix it.
  1249.  */
  1250. static void
  1251. cons(nbytes)            /* worker to do .byte etc statements */
  1252.                 /* clobbers input_line_pointer, checks */
  1253.                 /* end-of-line. */
  1254.      register int    nbytes;    /* 1=.byte, 2=.word, 4=.long */
  1255. {
  1256.   register char        c;
  1257.   register long int    mask;    /* High-order bits we will left-truncate, */
  1258.                 /* but includes sign bit also. */
  1259.   register long int     get;    /* what we get */
  1260.   register long int    use;    /* get after truncation. */
  1261.   register long int    unmask;    /* what bits we will store */
  1262.   register char *    p;
  1263.   register segT        segment;
  1264.            expressionS    exp;
  1265.   void    fix_new();
  1266.  
  1267.   /*
  1268.    * Input_line_pointer -> 1st char after pseudo-op-code and could legally
  1269.    * be a end-of-line. (Or, less legally an eof - which we cope with.)
  1270.    */
  1271.   /* JF << of >= number of bits in the object is undefined.  In particular
  1272.      SPARC (Sun 4) has problems */
  1273.   if(nbytes==sizeof(long int))
  1274.     mask = 0;
  1275.   else 
  1276.     mask = ~0 << (BITS_PER_CHAR * nbytes); /* Don't store these bits. */
  1277.   unmask = ~ mask;        /* Do store these bits. */
  1278. #ifdef NEVER
  1279.   "Do this mod if you want every overflow check to assume SIGNED 2's complement data.";
  1280.   mask = ~ (unmask >> 1);    /* Includes sign bit now. */
  1281. #endif
  1282.   /*
  1283.    * The following awkward logic is to parse ZERO or more expressions,
  1284.    * comma seperated. Recall an expression includes its leading &
  1285.    * trailing blanks. We fake a leading ',' if there is (supposed to
  1286.    * be) a 1st expression, and keep demanding 1 expression for each ','.
  1287.    */
  1288.   if (is_it_end_of_statement())
  1289.     {
  1290.       c = 0;            /* Skip loop. */
  1291.       input_line_pointer ++;    /* Matches end-of-loop 'correction'. */
  1292.     }
  1293.   else
  1294.     {
  1295.       c = ',';            /* Do loop. */
  1296.     }
  1297.   while ( c == ','  )
  1298.     {
  1299.       segment = expression( &exp ); /* At least scan over the expression. */
  1300.       if ( ! need_pass_2 )
  1301.     {            /* Still worthwhile making frags. */
  1302.  
  1303.       /* Don't call this if we are going to junk this pass anyway! */
  1304.       know( segment != SEG_PASS1 );
  1305.  
  1306.       if ( segment == SEG_DIFFERENCE && exp . X_add_symbol == NULL )
  1307.         {
  1308.           as_warn( "Subtracting symbol \"%s\"(segment\"%s\") is too hard. Absolute segment assumed.",
  1309.               exp . X_subtract_symbol -> sy_name,
  1310.               seg_name [(int) N_TYPE_seg [exp . X_subtract_symbol -> sy_type & N_TYPE]]);
  1311.           segment = SEG_ABSOLUTE;
  1312.           /* Leave exp . X_add_number alone. */
  1313.         }
  1314.       p = frag_more (nbytes);
  1315.       switch (segment)
  1316.         {
  1317.         case SEG_BIG:
  1318.           as_warn( "%s number illegal. Absolute 0 assumed.",
  1319.               exp . X_add_number > 0 ? "Bignum" : "Floating-Point");
  1320.           md_number_to_chars (p, (long)0, nbytes);
  1321.           break;
  1322.  
  1323.         case SEG_NONE:
  1324.           as_warn( "0 assumed for missing expression" );
  1325.           exp . X_add_number = 0;
  1326.           know( exp . X_add_symbol == NULL );
  1327.           /* fall into SEG_ABSOLUTE */
  1328.         case SEG_ABSOLUTE:
  1329.           get = exp . X_add_number;
  1330.           use = get & unmask;
  1331.           if ( (get & mask) && (get & mask) != mask )
  1332.         {        /* Leading bits contain both 0s & 1s. */
  1333.           as_warn("Value x%x truncated to x%x.", get, use);
  1334.         }
  1335.           md_number_to_chars (p, use, nbytes); /* put bytes in right order. */
  1336.           break;
  1337.  
  1338.         case SEG_BSS:
  1339.         case SEG_UNKNOWN:
  1340.         case SEG_TEXT:
  1341.         case SEG_DATA:
  1342.         case SEG_DIFFERENCE:
  1343.           fix_new (frag_now, p - frag_now -> fr_literal, nbytes,
  1344.                exp . X_add_symbol, exp . X_subtract_symbol,
  1345.                exp . X_add_number, 0);
  1346.           break;
  1347.  
  1348.         default:
  1349.           BAD_CASE( segment );
  1350.           break;
  1351.         }            /* switch(segment) */
  1352.     }            /* if(!need_pass_2) */
  1353.       c = * input_line_pointer ++;
  1354.     }                /* while(c==',') */
  1355.   input_line_pointer --;    /* Put terminator back into stream. */
  1356.   demand_empty_rest_of_line();
  1357. }                /* cons() */
  1358.  
  1359. /*
  1360.  *            big_cons()
  1361.  *
  1362.  * CONStruct more frag(s) of .quads, or .octa etc.
  1363.  * Makes 0 or more new frags.
  1364.  * If need_pass_2 == TRUE, generate no frag.
  1365.  * This understands only bignums, not expressions. Cons() understands
  1366.  * expressions.
  1367.  *
  1368.  * Constants recognised are '0...'(octal) '0x...'(hex) '...'(decimal).
  1369.  *
  1370.  * This creates objects with struct obstack_control objs, destroying
  1371.  * any context objs held about a partially completed object. Beware!
  1372.  *
  1373.  *
  1374.  * I think it sucks to have 2 different types of integers, with 2
  1375.  * routines to read them, store them etc.
  1376.  * It would be nicer to permit bignums in expressions and only
  1377.  * complain if the result overflowed. However, due to "efficiency"...
  1378.  */
  1379. static void
  1380. big_cons(nbytes)        /* worker to do .quad etc statements */
  1381.                 /* clobbers input_line_pointer, checks */
  1382.                 /* end-of-line. */
  1383.      register int    nbytes;    /* 8=.quad 16=.octa ... */
  1384. {
  1385.   register char        c;    /* input_line_pointer -> c. */
  1386.   register int        radix;
  1387.   register long int    length;    /* Number of chars in an object. */
  1388.   register int        digit;    /* Value of 1 digit. */
  1389.   register int        carry;    /* For multi-precision arithmetic. */
  1390.   register int        work;    /* For multi-precision arithmetic. */
  1391.   register char *    p;    /* For multi-precision arithmetic. */
  1392.  
  1393.   extern char hex_value[];    /* In hex_value.c. */
  1394.  
  1395.   /*
  1396.    * The following awkward logic is to parse ZERO or more strings,
  1397.    * comma seperated. Recall an expression includes its leading &
  1398.    * trailing blanks. We fake a leading ',' if there is (supposed to
  1399.    * be) a 1st expression, and keep demanding 1 expression for each ','.
  1400.    */
  1401.   if (is_it_end_of_statement())
  1402.     {
  1403.       c = 0;            /* Skip loop. */
  1404.     }
  1405.   else
  1406.     {
  1407.       c = ',';            /* Do loop. */
  1408.       -- input_line_pointer;
  1409.     }
  1410.   while (c == ',')
  1411.     {
  1412.       void grow_bignum();
  1413.  
  1414.       ++ input_line_pointer;
  1415.       SKIP_WHITESPACE();
  1416.       c = * input_line_pointer;
  1417.       /* C contains 1st non-blank character of what we hope is a number. */
  1418.       if (c == '0')
  1419.     {
  1420.       c = * ++ input_line_pointer;
  1421.       if (c == 'x' || c=='X')
  1422.         {
  1423.           c = * ++ input_line_pointer;
  1424.           radix = 16;
  1425.         }
  1426.       else
  1427.         {
  1428.           radix = 8;
  1429.         }
  1430.     }
  1431.       else
  1432.     {
  1433.       radix = 10;
  1434.     }
  1435.       /*
  1436.        * This feature (?) is here to stop people worrying about
  1437.        * mysterious zero constants: which is what they get when
  1438.        * they completely omit digits.
  1439.        */
  1440.       if (hex_value[c] >= radix)
  1441.     {
  1442.       as_warn( "Missing digits. 0 assumed." );
  1443.     }
  1444.       bignum_high = bignum_low - 1; /* Start constant with 0 chars. */
  1445.       for(   ;   (digit = hex_value [c]) < radix;   c = * ++ input_line_pointer)
  1446.     {
  1447.       /* Multiply existing number by radix, then add digit. */
  1448.       carry = digit;
  1449.       for (p=bignum_low;   p <= bignum_high;   p++)
  1450.         {
  1451.           work = (*p & MASK_CHAR) * radix + carry;
  1452.           *p = work & MASK_CHAR;
  1453.           carry = work >> BITS_PER_CHAR;
  1454.         }
  1455.       if (carry)
  1456.         {
  1457.           grow_bignum();
  1458.           * bignum_high = carry & MASK_CHAR;
  1459.           know( (carry & ~ MASK_CHAR) == 0);
  1460.         }
  1461.     }
  1462.       length = bignum_high - bignum_low + 1;
  1463.       if (length > nbytes)
  1464.     {
  1465.       as_warn( "Most significant bits truncated in integer constant." );
  1466.     }
  1467.       else
  1468.     {
  1469.       register long int    leading_zeroes;
  1470.  
  1471.       for(leading_zeroes = nbytes - length;
  1472.           leading_zeroes;
  1473.           leading_zeroes --)
  1474.         {
  1475.           grow_bignum();
  1476.           * bignum_high = 0;
  1477.         }
  1478.     }
  1479.       if (! need_pass_2)
  1480.     {
  1481.       p = frag_more (nbytes);
  1482.       bcopy (bignum_low, p, (int)nbytes);
  1483.     }
  1484.       /* C contains character after number. */
  1485.       SKIP_WHITESPACE();
  1486.       c = * input_line_pointer;
  1487.       /* C contains 1st non-blank character after number. */
  1488.     }
  1489.   demand_empty_rest_of_line();
  1490. }                /* big_cons() */
  1491.  
  1492. static void
  1493. grow_bignum()            /* Extend bignum by 1 char. */
  1494. {
  1495.   register long int    length;
  1496.  
  1497.   bignum_high ++;
  1498.   if (bignum_high >= bignum_limit)
  1499.     {
  1500.       length = bignum_limit - bignum_low;
  1501.       bignum_low = xrealloc (bignum_low, length + length);
  1502.       bignum_high = bignum_low + length;
  1503.       bignum_limit = bignum_low + length + length;
  1504.     }
  1505. }                /* grow_bignum(); */
  1506.  
  1507. /*
  1508.  *            float_cons()
  1509.  *
  1510.  * CONStruct some more frag chars of .floats .ffloats etc.
  1511.  * Makes 0 or more new frags.
  1512.  * If need_pass_2 == TRUE, no frags are emitted.
  1513.  * This understands only floating literals, not expressions. Sorry.
  1514.  *
  1515.  * A floating constant is defined by atof_generic(), except it is preceded
  1516.  * by 0d 0f 0g or 0h. After observing the STRANGE way my BSD AS does its
  1517.  * reading, I decided to be incompatible. This always tries to give you
  1518.  * rounded bits to the precision of the pseudo-op. Former AS did premature
  1519.  * truncatation, restored noisy bits instead of trailing 0s AND gave you
  1520.  * a choice of 2 flavours of noise according to which of 2 floating-point
  1521.  * scanners you directed AS to use.
  1522.  *
  1523.  * In:    input_line_pointer -> whitespace before, or '0' of flonum.
  1524.  *
  1525.  */
  1526. void    /* JF was void, but can't be if VAX.C is goning to use it */
  1527. float_cons(float_type)        /* Worker to do .float etc statements. */
  1528.                 /* Clobbers input_line-pointer, checks end-of-line. */
  1529.      register char    float_type;    /* 'f':.ffloat ... 'F':.float ... */
  1530. {
  1531.   register char *    p;
  1532.   register char        c;
  1533.   int    length;    /* Number of chars in an object. */
  1534.   register char *    err;    /* Error from scanning floating literal. */
  1535.   char        temp [MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
  1536.  
  1537.   /*
  1538.    * The following awkward logic is to parse ZERO or more strings,
  1539.    * comma seperated. Recall an expression includes its leading &
  1540.    * trailing blanks. We fake a leading ',' if there is (supposed to
  1541.    * be) a 1st expression, and keep demanding 1 expression for each ','.
  1542.    */
  1543.   if (is_it_end_of_statement())
  1544.     {
  1545.       c = 0;            /* Skip loop. */
  1546.       ++ input_line_pointer;    /* -> past termintor. */
  1547.     }
  1548.   else
  1549.     {
  1550.       c = ',';            /* Do loop. */
  1551.     }
  1552.   while (c == ',')
  1553.     {
  1554.       /* input_line_pointer -> 1st char of a flonum (we hope!). */
  1555.       SKIP_WHITESPACE();
  1556.       /* Skip any 0{letter} that may be present. Don't even check if the
  1557.        * letter is legal. Someone may invent a "z" format and this routine
  1558.        * has no use for such information. Lusers beware: you get
  1559.        * diagnostics if your input is ill-conditioned.
  1560.        */
  1561.       if(input_line_pointer[0]=='0' && isalpha(input_line_pointer[1]))
  1562.       input_line_pointer+=2;
  1563.  
  1564.       err = md_atof (float_type, temp, &length);
  1565.       know( length <=  MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
  1566.       know( length > 0 );
  1567.       if (* err)
  1568.     {
  1569.       as_warn( "Bad floating literal: %s", err);
  1570.       ignore_rest_of_line();
  1571.       /* Input_line_pointer -> just after end-of-line. */
  1572.       c = 0;        /* Break out of loop. */
  1573.     }
  1574.       else
  1575.     {
  1576.       if ( ! need_pass_2)
  1577.         {
  1578.           p = frag_more (length);
  1579.           bcopy (temp, p, length);
  1580.         }
  1581.       SKIP_WHITESPACE();
  1582.       c = * input_line_pointer ++;
  1583.       /* C contains 1st non-white character after number. */
  1584.       /* input_line_pointer -> just after terminator (c). */
  1585.     }
  1586.     }
  1587.   -- input_line_pointer;        /* -> terminator (is not ','). */
  1588.   demand_empty_rest_of_line();
  1589. }                /* float_cons() */
  1590.  
  1591. /*
  1592.  *            stringer()
  1593.  *
  1594.  * We read 0 or more ',' seperated, double-quoted strings.
  1595.  *
  1596.  * Caller should have checked need_pass_2 is FALSE because we don't check it.
  1597.  */
  1598. static void
  1599. stringer(append_zero)        /* Worker to do .ascii etc statements. */
  1600.                 /* Checks end-of-line. */
  1601.      register int append_zero;    /* 0: don't append '\0', else 1 */
  1602. {
  1603.   /* register char *    p; JF unused */
  1604.   /* register int        length; JF unused */    /* Length of string we read, excluding */
  1605.                 /* trailing '\0' implied by closing quote. */
  1606.   /* register char *    where; JF unused */
  1607.   /* register fragS *    fragP; JF unused */
  1608.   register int c;
  1609.  
  1610.   /*
  1611.    * The following awkward logic is to parse ZERO or more strings,
  1612.    * comma seperated. Recall a string expression includes spaces
  1613.    * before the opening '\"' and spaces after the closing '\"'.
  1614.    * We fake a leading ',' if there is (supposed to be)
  1615.    * a 1st, expression. We keep demanding expressions for each
  1616.    * ','.
  1617.    */
  1618.   if (is_it_end_of_statement())
  1619.     {
  1620.       c = 0;            /* Skip loop. */
  1621.       ++ input_line_pointer;    /* Compensate for end of loop. */
  1622.     }
  1623.   else
  1624.     {
  1625.       c = ',';            /* Do loop. */
  1626.     }
  1627.   for (   ;   c == ',';   c = *input_line_pointer ++)
  1628.     {
  1629.       SKIP_WHITESPACE();
  1630.       if (* input_line_pointer == '\"')
  1631.     {
  1632.       ++ input_line_pointer; /* -> 1st char of string. */
  1633.       while ( (c = next_char_of_string()) >= 0)
  1634.         {
  1635.           FRAG_APPEND_1_CHAR( c );
  1636.         }
  1637.       if (append_zero)
  1638.         {
  1639.           FRAG_APPEND_1_CHAR( 0 );
  1640.         }
  1641.       know( input_line_pointer [-1] == '\"' );
  1642.     }
  1643.       else
  1644.     {
  1645.       as_warn( "Expected \"-ed string" );
  1646.     }
  1647.       SKIP_WHITESPACE();
  1648.     }
  1649.   -- input_line_pointer;
  1650.   demand_empty_rest_of_line();
  1651. }                /* stringer() */
  1652.  
  1653. static int
  1654. next_char_of_string ()
  1655. {
  1656.   register int c;
  1657.  
  1658.   c = * input_line_pointer ++;
  1659.   switch (c)
  1660.     {
  1661.     case '\"':
  1662.       c = -1;
  1663.       break;
  1664.  
  1665.     case '\\':
  1666.       switch (c = * input_line_pointer ++)
  1667.     {
  1668.     case 'b':
  1669.       c = '\b';
  1670.       break;
  1671.  
  1672.     case 'f':
  1673.       c = '\f';
  1674.       break;
  1675.  
  1676.     case 'n':
  1677.       c = '\n';
  1678.       break;
  1679.  
  1680.     case 'r':
  1681.       c = '\r';
  1682.       break;
  1683.  
  1684.     case 't':
  1685.       c = '\t';
  1686.       break;
  1687.  
  1688.     case '\\':
  1689.     case '"':
  1690.       break;        /* As itself. */
  1691.  
  1692.     case '0':
  1693.     case '1':
  1694.     case '2':
  1695.     case '3':
  1696.     case '4':
  1697.     case '5':
  1698.     case '6':
  1699.     case '7':
  1700.     case '8':
  1701.     case '9':
  1702.       {
  1703.         long int number;
  1704.  
  1705.         for (number = 0;   isdigit(c);   c = * input_line_pointer ++)
  1706.           {
  1707.         number = number * 8 + c - '0';
  1708.           }
  1709.         c = number;
  1710.       }
  1711.       -- input_line_pointer;
  1712.       break;
  1713.  
  1714.     case '\n':
  1715. /*      as_fatal( "Unterminated string - use app!" ); */
  1716. /* To be compatible with BSD 4.2 as: give the luser a linefeed!! */
  1717.       c = '\n';
  1718.       break;
  1719.  
  1720.     default:
  1721.       as_warn( "Bad escaped character in string, '?' assumed" );
  1722.       c = '?';
  1723.       break;
  1724.     }
  1725.       break;
  1726.  
  1727.     default:
  1728.       break;
  1729.     }
  1730.   return (c);
  1731. }
  1732.  
  1733. static segT
  1734. get_segmented_expression ( expP )
  1735.      register expressionS *    expP;
  1736. {
  1737.   register segT        retval;
  1738.  
  1739.   if ( (retval = expression( expP )) == SEG_PASS1 || retval == SEG_NONE || retval == SEG_BIG )
  1740.     {
  1741.       as_warn("Expected address expression: absolute 0 assumed");
  1742.       retval = expP -> X_seg = SEG_ABSOLUTE;
  1743.       expP -> X_add_number   = 0;
  1744.       expP -> X_add_symbol   = expP -> X_subtract_symbol = 0;
  1745.     }
  1746.   return (retval);        /* SEG_ ABSOLUTE,UNKNOWN,DATA,TEXT,BSS */
  1747. }
  1748.  
  1749. static segT
  1750. get_known_segmented_expression ( expP )
  1751.      register expressionS *    expP;
  1752. {
  1753.   register segT        retval;
  1754.   register char *    name1;
  1755.   register char *    name2;
  1756.  
  1757.   if (   (retval = get_segmented_expression (expP)) == SEG_UNKNOWN
  1758.       )
  1759.     {
  1760.       name1 = expP -> X_add_symbol ? expP -> X_add_symbol -> sy_name : "";
  1761.       name2 = expP -> X_subtract_symbol ? expP -> X_subtract_symbol -> sy_name : "";
  1762.       if ( name1 && name2 )
  1763.     {
  1764.       as_warn("Symbols \"%s\" \"%s\" are undefined: absolute 0 assumed.",
  1765.           name1, name2);
  1766.     }
  1767.       else
  1768.     {
  1769.       as_warn("Symbol \"%s\" undefined: absolute 0 assumed.",
  1770.           name1 ? name1 : name2);
  1771.     }
  1772.       retval = expP -> X_seg = SEG_ABSOLUTE;
  1773.       expP -> X_add_number   = 0;
  1774.       expP -> X_add_symbol   = expP -> X_subtract_symbol = NULL;
  1775.     }
  1776.  know(   retval == SEG_ABSOLUTE || retval == SEG_DATA || retval == SEG_TEXT || retval == SEG_BSS || retval == SEG_DIFFERENCE );
  1777.   return (retval);
  1778. }                /* get_known_segmented_expression() */
  1779.  
  1780.  
  1781.  
  1782. /* static */ long int /* JF was static, but can't be if the MD pseudos are to use it */
  1783. get_absolute_expression ()
  1784. {
  1785.   expressionS    exp;
  1786.   register segT s;
  1787.  
  1788.   if ( (s = expression(& exp)) != SEG_ABSOLUTE )
  1789.     {
  1790.       if ( s != SEG_NONE )
  1791.     {
  1792.       as_warn( "Bad Absolute Expression, absolute 0 assumed.");
  1793.     }
  1794.       exp . X_add_number = 0;
  1795.     }
  1796.   return (exp . X_add_number);
  1797. }
  1798.  
  1799. static char            /* return terminator */
  1800. get_absolute_expression_and_terminator( val_pointer)
  1801.      long int *        val_pointer; /* return value of expression */
  1802. {
  1803.   * val_pointer = get_absolute_expression ();
  1804.   return ( * input_line_pointer ++ );
  1805. }
  1806.  
  1807. /*
  1808.  *            demand_copy_C_string()
  1809.  *
  1810.  * Like demand_copy_string, but return NULL if the string contains any '\0's.
  1811.  * Give a warning if that happens.
  1812.  */
  1813. static char *
  1814. demand_copy_C_string (len_pointer)
  1815.      int *    len_pointer;
  1816. {
  1817.   register char *    s;
  1818.  
  1819.   if (s = demand_copy_string (len_pointer))
  1820.     {
  1821.       register int    len;
  1822.  
  1823.       for (len = * len_pointer;
  1824.        len > 0;
  1825.        len--)
  1826.     {
  1827.       if (* s == 0)
  1828.         {
  1829.           s = 0;
  1830.           len = 1;
  1831.           * len_pointer = 0;
  1832.           as_warn( "This string may not contain \'\\0\'" );
  1833.         }
  1834.     }
  1835.     }
  1836.   return (s);
  1837. }
  1838.  
  1839. /*
  1840.  *            demand_copy_string()
  1841.  *
  1842.  * Demand string, but return a safe (=private) copy of the string.
  1843.  * Return NULL if we can't read a string here.
  1844.  */
  1845. static char *
  1846. demand_copy_string (lenP)
  1847.      int *    lenP;
  1848. {
  1849.   register int        c;
  1850.   register int        len;
  1851.        char *    retval;
  1852.  
  1853.   len = 0;
  1854.   SKIP_WHITESPACE();
  1855.   if (* input_line_pointer == '\"')
  1856.     {
  1857.       input_line_pointer ++;    /* Skip opening quote. */
  1858.       while ( (c = next_char_of_string()) >= 0 ) {
  1859.       obstack_1grow ( ¬es, c );
  1860.       len ++;
  1861.     }
  1862.       /* JF this next line is so demand_copy_C_string will return a null
  1863.          termanated string. */
  1864.       obstack_1grow(¬es,'\0');
  1865.       retval=obstack_finish( ¬es);
  1866.   } else {
  1867.       as_warn( "Missing string" );
  1868.       retval = NULL;
  1869.       ignore_rest_of_line ();
  1870.     }
  1871.   * lenP = len;
  1872.   return (retval);
  1873. }
  1874.  
  1875. /*
  1876.  *        is_it_end_of_statement()
  1877.  *
  1878.  * In:    Input_line_pointer -> next character.
  1879.  *
  1880.  * Do:    Skip input_line_pointer over all whitespace.
  1881.  *
  1882.  * Out:    TRUE if input_line_pointer -> end-of-line.
  1883.  */
  1884. static int
  1885. is_it_end_of_statement()
  1886. {
  1887.   SKIP_WHITESPACE();
  1888.   return (is_end_of_line [* input_line_pointer]);
  1889. }
  1890.  
  1891.  
  1892. equals(sym_name)
  1893. char *sym_name;
  1894. {
  1895.   register struct symbol * symbolP; /* symbol we are working with */
  1896.  
  1897.   symbolP=symbol_find_or_make(sym_name);
  1898.   if(input_line_pointer[1]=='=')
  1899.     input_line_pointer+=2;
  1900.   else
  1901.     *input_line_pointer++='=';        /* Put it back */
  1902.   pseudo_set(symbolP);
  1903. }
  1904.  
  1905. /* end: read.c */
  1906.